/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.base.common.util.collection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import com.base.common.base.CreatorFactory;

/**
 * 多值的Map,内部为Map<K,Collection<V>>. <br>
 * 使用的本类的目的为代替一下代码,提高开发效率和整洁度:<br>
 * 
 * <code>
 * Map<String,List<String>> map = new HashMap<String,List<String>>();
 * List<String> list = map.get("key");
 * if(list == null{
 * 		list = new ArrayList<String>();
 * }
 * list.add(value);
 * 
 * 为
 * MultiMap<String,String> multiMap = MultiValueMap.arrayListMultiValueMap();
 * multiMap.putItem(key,value);
 * </code>
 * 
 */
public class MultiValueMap<K, V> extends AbstractMapDecorator<K, Collection<V>> implements MultiMap<K, V> {

	private static final long serialVersionUID = -8812312089932013780L;

	private CreatorFactory<Collection<V>> collectionFactory;

	public MultiValueMap() {
		this(new HashMap<K, Collection<V>>(), new ArrayListFactory<V>());
	}

	public MultiValueMap(Map<K, Collection<V>> map) {
		this(map, new ArrayListFactory<V>());
	}

	public MultiValueMap(Map<K, Collection<V>> map, CreatorFactory<Collection<V>> factory) {
		super(map);
		collectionFactory = factory;
	}

	private Collection<V> createCollection() {
		return collectionFactory.create();
	}

	@Override
	public V removeItem(K key, V item) {
		Collection<V> c = get(key);
		if (c == null || c.remove(item)) {
			return item;
		}
		return null;
	}

	@Override
	public boolean putItem(K key, V value) {
		Collection<V> c = get(key);
		if (c == null) {
			c = createCollection();
			put(key, c);
		}
		return c.add(value);
	}

	@Override
	public Collection<V> itemValues() {
		Collection<V> c = createCollection();
		for (Map.Entry<K, Collection<V>> entry : this.entrySet()) {
			c.addAll(entry.getValue());
		}
		return c;
	}

	@Override
	public boolean containsItemValue(K key, V value) {
		Collection<V> c = get(key);
		if (c == null || !c.contains(value)) {
			return false;
		}
		return true;
	}

	public static <SK, SV> MultiValueMap<SK, SV> hashSetMultiValueMap() {
		return new MultiValueMap<SK, SV>(new HashMap<SK, Collection<SV>>(), new HashSetFactory<SV>());
	}

	public static <SK, SV> MultiValueMap<SK, SV> arrayListMultiValueMap() {
		return new MultiValueMap<SK, SV>(new HashMap<SK, Collection<SV>>(), new ArrayListFactory<SV>());
	}

	private static class ArrayListFactory<E> implements CreatorFactory<Collection<E>> {
		@Override
		public Collection<E> create() {
			return new ArrayList<E>();
		}
	}

	private static class HashSetFactory<E> implements CreatorFactory<Collection<E>> {
		@Override
		public Collection<E> create() {
			return new HashSet<E>();
		}
	}

}
